001 /** 002 * Java Gui Builder - A library to build GUIs using an XML file. 003 * Copyright 2002, 2003 (C) François Beausoleil 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library; if not, write to the Free Software 017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018 */ 019 020 package jgb.handlers.swing; 021 022 import jgb.builder.TagHandler; 023 import jgb.builder.WindowContext; 024 import org.xml.sax.SAXException; 025 026 import java.lang.reflect.InvocationHandler; 027 import java.lang.reflect.Method; 028 import java.lang.reflect.Proxy; 029 import java.util.EventObject; 030 import java.util.Map; 031 032 public class RegisterTagHandler extends AbstractTagHandler { 033 public static final String ATTR_METHOD = "method"; 034 public static final String ATTR_MANAGER = "manager"; 035 public static final String ATTR_EVENT = "event"; 036 037 protected void enterElement(Map atts) throws SAXException { 038 String className = (String)atts.get(ATTR_CLASS); 039 String eventName = (String)atts.get(ATTR_EVENT); 040 String managerName = (String)atts.get(ATTR_MANAGER); 041 String methodName = (String)atts.get(ATTR_METHOD); 042 043 try { 044 Class listenerClass; 045 try { 046 listenerClass = Class.forName(className); 047 } catch (ClassNotFoundException e) { 048 try { 049 listenerClass = Class.forName("java.awt.event." + className); 050 } catch (ClassNotFoundException e1) { 051 listenerClass = Class.forName("javax.swing.event." + className); 052 } 053 } 054 055 if (!listenerClass.isInterface()) { 056 throwParsingException("register listener class must be an interface", 057 new IllegalArgumentException(listenerClass.getName())); 058 } 059 060 final Object managerObject = getObject(managerName); 061 final Method reflectedEventMethod = managerObject.getClass() 062 .getMethod(methodName, 063 new Class[]{ 064 EventObject.class, 065 WindowContext.class} 066 ); 067 final Object listenerInstance = Proxy.newProxyInstance( 068 this.getClass().getClassLoader(), 069 new Class[]{listenerClass}, 070 new EventReflector( 071 eventName, managerObject, reflectedEventMethod, 072 (WindowContext)tagContext.get(TagHandler.WINDOW_CONTEXT_KEY) 073 ) 074 ); 075 076 final Object parentObject = getCurrentObject(); 077 final Class parentObjectClass = parentObject.getClass(); 078 final String listenerClassName; 079 final int lastDot = listenerClass.getName().lastIndexOf('.'); 080 listenerClassName = listenerClass.getName().substring(1 + lastDot); 081 final Method addListenerMethod = parentObjectClass.getMethod( 082 "add" + listenerClassName, new Class[]{listenerClass}); 083 addListenerMethod.invoke(parentObject, 084 new Object[]{listenerInstance}); 085 } catch (SAXException e) { 086 throw e; 087 } catch (Exception e) { 088 throwParsingException("Unable to register event listener for event " + 089 eventName + " on object " + getCurrentObjectId() + " for " + 090 "class " + className, e); 091 } 092 } 093 094 protected void exitElement() throws SAXException { 095 } 096 097 private static final class EventReflector implements InvocationHandler { 098 private final String eventName; 099 private final Object managerObject; 100 private final Method reflectedEventMethod; 101 private final WindowContext windowContext; 102 103 public EventReflector(String eventName, Object managerObject, Method reflectedEventMethod, WindowContext windowContext) { 104 this.eventName = eventName; 105 this.managerObject = managerObject; 106 this.reflectedEventMethod = reflectedEventMethod; 107 this.windowContext = windowContext; 108 } 109 110 public Object invoke(Object proxy, Method method, Object[] args) 111 throws Throwable { 112 if (eventName.equals(method.getName())) { 113 reflectedEventMethod.invoke( 114 managerObject, 115 new Object[]{args[0], windowContext} 116 ); 117 } 118 return null; 119 } 120 } 121 }